<?php
/*
  Обёртка для форм-процессора:
  * реализация принципа "один конфиг - одна форма" при работе с форм-процессором
  * see http://in.jetstyle.ru/rocket/rocketforms
  * see http://in.jetstyle.ru/rocket/rocketforms/specs/easyforms
  
  Управляющий класс.
  
  EasyForm( &$rh, $config=false )
      - $rh              -- ссылка на RH, как обычно
      - $config          -- конфиг-массив, если есть, то сразу запускается обработка
  
  -------------------
  
  function Handle( $config,
                    $ignore_post     =false,  $ignore_load   =false, 
                    $ignore_validator=false,  $ignore_session=false )
      - $config -- конфиг-массив формы
      - $ignore* -- аналогично параметрам Form::Handle()
    Строит форму на основе конфиг-массиа и запускает на обработку.
  
  AddFields( &$form, $config, $is_field=false )
      - $form -- ссылка на объект класса Form или FormField
      - $config -- конфиг-массив, содержащий информацию о полях
      - $is_field -- true, если $form является объектом класса FormField
    Добавляет поля к форме или группе.
  
  AddButtons( &$form, $config )
      - $form -- ссылка на объект класса Form
      - $config -- конфиг-массив, содержащий информацию о кнопках
    Добавляет кнопки к форме.
  
  ConstructConfig( $conf_name, $_config=false )
      - $conf_name -- имя пакета с конфигом поля или кнопки
      - $_config -- конфиг-массив с изменёнными параметрами
    Генерирует конифиг-массив для поля или кнопки на основе пакета.
    Пакеты хранятся в handlers/FormPackages/:
      поле: [conf_name].php
      кнопка: button_[conf_name].php
    Значения из $_config перекрывают значения из пакета.
  
*/
  
class EasyForm{
  
  //ссылки на окружение
  var $rh;
  var $tpl;
  
  var $form; //объект класса Form  
  var $id_var_name = "_id"; //из какой переменной запроса брать ID  к записи в БД
  var $groups = array("group","tab_list","tab_child"); //список пакетов, которые считаются группами
  
  /*
    Вариация врапперов в зависимости от того, в группе эелемент или нет.
    Если вариация не найдена, поле выводится с прописанным в пакете враппером.
  */
  var $wrapper_tpl = array(
    "number,radio,select,string,password" => array( "wrapper.html:Div", "wrapper.html:Row" ),
    "textarea"                            => array( "wrapper.html:Div", "wrapper.html:RowSpan" ),
  );
  
  //конструктор
  //возможно, сразу же построение и обработка формы
  function EasyForm( &$rh, $config=false ){
    
    $this->rh =& $rh;
    $this->tpl =& $rh->tpl;
    
    if( $config )
      $this->Handle($config);
  }
  
  //построение формы, обработка формы
  function Handle( $config,
                    $ignore_post     =false,  $ignore_load   =false, 
                    $ignore_validator=false,  $ignore_session=false ){
    
    if(!is_array($config))
      $this->rh->error("EasyForm::Handle -- \$config should be an array, now it is: <strong>[$config]</strong>");
    
    //инициализируем форму
    $class_name = isset($config["form"]["class"]) ? $config["form"]["class"] : "Form";
    $this->rh->UseClass( $class_name );
    eval("\$form =& new ".$class_name."( \$this->rh, \$config[\"form\"] );");
    $this->form =& $form;
    
    //привязываем строку к БД
    if( $id = isset($config["id"]) ? $config["id"] : false )
      $form->AssignId( $id );
    else
      if( $id = isset($_REQUEST[ $this->id_var_name ]) ? $_REQUEST[ $this->id_var_name ] : false )
        $form->AssignId( $id );
    
    //добавляем поля
    $this->AddFields( $form, $config["fields"] );
    
    //добавляем кнопки
    $this->AddButtons( $form, $config["buttons"] );
    
    //поехали!
    return $form->Handle( $ignore_post, $ignore_load, $ignore_validator, $ignore_session );
  }
  
  //добавляем поля к форме или группе
  function AddFields( &$form, $config, $is_field=false ){
    
    if(!is_array($config))
      $this->rh->debug->Error("EasyForm::AddFields -- \$config should be an array, now it is: <strong>[$config]</strong>");
    
    //тут добавляем поля
    foreach($config as $name=>$rec){
      //формируем конфиг для поля
      if( is_array($rec) ){
        $pack_name = $rec[0];
        $conf = $rec[1];
      }else{
        $pack_name = $rec;
        $conf = array();
      }
      //определяем wrapper_tpl
      if( !isset($conf["wrapper_tpl"]) )
        foreach( $this->wrapper_tpl as $k=>$v){
          if( in_array($pack_name, explode(",",$k) ) ){
            $conf["wrapper_tpl"] = $v[ $is_field ? 1 : 0 ];
            break;
          }
        }
      //генерируем конфиг для поля
      $conf = $this->ConstructConfig( $pack_name, $conf );
      //создаём поле
      if($is_field)
        $field =& $form->model->Model_AddField( $name, $conf );
      else
        $field =& $form->AddField( $name, $conf );
      //если указан пакет группы, обрабатываем вложение
      if( in_array($rec[0],$this->groups) )
        $this->AddFields( $field, $rec[2], true );
    }
  }
  
  //добавляем кнопки к форме
  function AddButtons( &$form, $config ){
    
    if(!is_array($config))
      $this->rh->error("EasyForm::AddButtons -- \$config should be an array, now it is: <strong>[$config]</strong>");
    
    //тут добавляем кнопки
    foreach($config as $rec){
      //формируем конфиг для кнопки
      if( is_array($rec) )
        $conf = $this->ConstructConfig( "button_".$rec[0], $rec[1] );
      else
        $conf = $this->ConstructConfig( "button_".$rec );
      //создаём кнопку
      $field =& $form->AddButton( $conf );
    }
  }
  
  //формирует конфиг на основе пакета
  function ConstructConfig( $conf_name, $_config=false ){
    
    //конструируем конфиг
    $config = array();
    include( $this->rh->FindScript_("handlers","FormPackages/".$conf_name) );
    
    //возвращаем смесь из пакета и твиков
    return is_array($_config) ? array_merge($config,$_config) : $config ;
  }
}

?>